package cn.yoline.xylink.view;

import android.content.Context;
import android.log.L;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.ainemo.module.call.data.Enums;
import com.ainemo.sdk.otf.NemoSDK;
import com.ainemo.sdk.otf.VideoInfo;

import java.util.ArrayList;
import java.util.List;


/**
 * Copyright 2020 JxGIS
 *
 * @file FullScreenVideoView
 * @auth linaisheng
 * Created on 2022/7/27.
 * Description：
 */
public class FullScreenVideoView extends VideoCellGroup {

    private static final String TAG = "FullScreenVideoView";
    private static final int THUMBNAIL_H = 10;
    private static final int THUMBNAIL_W = 16;
    private static final int RATIO_HEIGHT = 9;
    private static final int RATIO_WIDTH = 16;
    private static final int THUMBNAIL_CELL_NUM = 6;

    public FullScreenVideoView(Context context) {
        super(context);
    }

    public FullScreenVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FullScreenVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (getWidth() > getHeight()) {
            layoutLandscape(l, t, r, b);
        } else if (getHeight() > getWidth()) {
            layoutPortrait(l, t, r, b);
        }
    }

    private void layoutLandscape(int l, int t, int r, int b) {
        computeVideoCellOrders();
        layoutFullScreenVideoCell(l, t, r, b);
        layoutThumbnailVideoCell(l, t, r, b);
        checkPip();
    }

    private void layoutPortrait(int l, int t, int r, int b) {
        computeVideoCellOrders();
        switch (mRemoteVideoCells.size()) {
            case 1:
                layoutFullScreenVideoCell(l, t, r, b);
                break;
            case 2:
                layoutTwoCells(l, t, r, b);
                break;
            default:
                layoutMoreCells(l, t, r, b);
                break;
        }
    }

    private void layoutTwoCells(int l, int t, int r, int b) {
        if (mRemoteVideoCells.size() == 2) {

            mRemoteVideoCells.get(0).setLargeScreen(true);
            mRemoteVideoCells.get(0).setFullScreen(true);
            mRemoteVideoCells.get(0).setRectVisible(false);
            mRemoteVideoCells.get(0).setVisibility(VISIBLE);

            VideoInfo layoutInfo = mRemoteVideoCells.get(0).getLayoutInfo();

            if (layoutInfo != null && layoutInfo.isContent()) {
                L.i(TAG, "full.cell.info : " + layoutInfo);
                mRemoteVideoCells.get(0).layout(l, t, r, b);
            } else if (layoutInfo != null && layoutInfo.getVideoWidth() > layoutInfo.getVideoHeight()
                    || NemoSDK.getLocalVideoStreamID().equals(layoutInfo.getDataSourceID())
                    || !layoutInfo.getRemoteID().contains(Enums.DEVICE_TYPE_SOFT)) {
                L.i(TAG, "layout.getRemoteID: " + layoutInfo.getRemoteID());
                int height = (r - l) * RATIO_HEIGHT / RATIO_WIDTH;
                int start = ((b - t) - height) / 2;
                mRemoteVideoCells.get(0).layout(l, start, r, start + height);
            } else {
                int height = (r - l) * 4 / 3;
                mRemoteVideoCells.get(0).layout(l, t, r, b);
            }

            //获取新的大屏
            mFullScreenVideoCell = mRemoteVideoCells.get(0);
            if (onVideoCellListener != null) {
                onVideoCellListener.onFullScreenChanged(mFullScreenVideoCell);
            }

            L.i(TAG, "remote id: " + mRemoteVideoCells.get(1).getId());

            int cellHeight = ((b - t) - (THUMBNAIL_CELL_NUM + 1) * mCellPadding) / THUMBNAIL_CELL_NUM;
            int cellWidth = cellHeight * THUMBNAIL_H / THUMBNAIL_W;

            int left = r - l - mCellPadding - cellWidth;
            int top = mCellPadding;
            int right = r - l - mCellPadding;
            int bottom = t + mCellPadding + cellHeight;

            mRemoteVideoCells.get(1).setLargeScreen(false);
            mRemoteVideoCells.get(1).setFullScreen(false);
            mRemoteVideoCells.get(1).setRectVisible(true);
            mRemoteVideoCells.get(1).setVisibility(VISIBLE);
            mRemoteVideoCells.get(1).bringToFront();

            mRemoteVideoCells.get(1).layout(left, top, right, bottom);

        }
    }

    private void layoutMoreCells(int l, int t, int r, int b) {
        if (mRemoteVideoCells.size() >= 3) {
            int cellWidth = (r - l) / 2;
            int cellHeight = cellWidth * RATIO_HEIGHT / RATIO_WIDTH;

            int left = 0, top = 0, right = 0, bottom = 0, size = mRemoteVideoCells.size() - 1;


            top = ((b - t) - (2 * cellHeight + cellHeight * (size / 2 + size % 2))) / 2;

            if (top < 0) {
                cellHeight = (b - t) / (2 + (size / 2 + size % 2));
                cellWidth = cellHeight * RATIO_WIDTH / RATIO_HEIGHT;
                top = t;
            }

            left = ((r - l) - cellWidth * 2) / 2;
            right = left + cellWidth * 2;
            bottom = top + 2 * cellHeight;

            mRemoteVideoCells.get(0).setLargeScreen(true);
            mRemoteVideoCells.get(0).setFullScreen(false);
            mRemoteVideoCells.get(0).setRectVisible(false);
            mRemoteVideoCells.get(0).setVisibility(VISIBLE);
            mRemoteVideoCells.get(0).layout(left, top, right, bottom);
            L.i(TAG, "layoutMoreCells, left : " + left + ", top : " + top + ", right : " + right + ", bottom : " + bottom);

            //获取新的大屏
            mFullScreenVideoCell = mRemoteVideoCells.get(0);
            if (onVideoCellListener != null) {
                onVideoCellListener.onFullScreenChanged(mFullScreenVideoCell);
            }

            for (int i = 1; i < mRemoteVideoCells.size(); i++) {
                if (i % 2 == 1) {
                    left = ((r - l) - cellWidth * 2) / 2;
                    top = bottom;
                    right = left + cellWidth;
                    bottom = top + cellHeight;
                    mRemoteVideoCells.get(i).setLargeScreen(true);
                    mRemoteVideoCells.get(i).setFullScreen(false);
                    mRemoteVideoCells.get(i).setRectVisible(false);
                    mRemoteVideoCells.get(i).setVisibility(VISIBLE);
                    mRemoteVideoCells.get(i).layout(left, top, right, bottom);
                } else {
                    left = right;
                    right = left + cellWidth;
                    mRemoteVideoCells.get(i).setLargeScreen(true);
                    mRemoteVideoCells.get(i).setFullScreen(false);
                    mRemoteVideoCells.get(i).setRectVisible(false);
                    mRemoteVideoCells.get(i).setVisibility(VISIBLE);
                    mRemoteVideoCells.get(i).layout(left, top, right, bottom);
                }
            }
        }
    }

    private void layoutFullScreenVideoCell(int l, int t, int r, int b) {

        if (mRemoteVideoCells.size() > 0) {

            //获取新的大屏
            mFullScreenVideoCell = mRemoteVideoCells.get(0);

            mFullScreenVideoCell.setFullScreen(true);
            mFullScreenVideoCell.setRectVisible(false);
            if (mFullScreenVideoCell.getLayoutInfo() != null && mFullScreenVideoCell.getLayoutInfo().isContent()) {
                mFullScreenVideoCell.layout(l, t, r, b);
            } else if (mFullScreenVideoCell.getLayoutInfo() != null
                    && mFullScreenVideoCell.getLayoutInfo().getVideoHeight() > mFullScreenVideoCell.getLayoutInfo().getVideoWidth()) {
                int height = b - t;
                int width = height * 3 / 4;

                mFullScreenVideoCell.layout((r - l - width) / 2, t, (r - l + width) / 2, b);
            } else {
                mFullScreenVideoCell.layout(l, t, r, b);
            }
            if (onVideoCellListener != null) {
                onVideoCellListener.onFullScreenChanged(mFullScreenVideoCell);
            }
        }


        L.i(TAG, "layoutFullScreenVideoCell, layoutInfo : " + (mFullScreenVideoCell != null ? mFullScreenVideoCell.getLayoutInfo() : null));
    }

    private void layoutThumbnailVideoCell(int l, int t, int r, int b) {
        int cellWidth = ((r - l) - (THUMBNAIL_CELL_NUM + 1) * mCellPadding) / THUMBNAIL_CELL_NUM;
        int cellHeight = cellWidth * THUMBNAIL_H / THUMBNAIL_W;


        if (mRemoteVideoCells.size() > 1) {
            for (int i = 1; i < mRemoteVideoCells.size(); i++) {
                int left = mCellPadding + (i - 1) * (cellWidth + mCellPadding);
                int top = (b - t) - (cellHeight + mCellPadding);
                int right = (mCellPadding + cellWidth) * i;
                int bottom = (b - t) - mCellPadding;

                mRemoteVideoCells.get(i).setLargeScreen(false);
                mRemoteVideoCells.get(i).setFullScreen(false);
                mRemoteVideoCells.get(i).setRectVisible(true);

                mRemoteVideoCells.get(i).layout(left, top, right, bottom);

                mRemoteVideoCells.get(i).bringToFront();
            }
        }

    }

    private void checkPip() {
        for (int i = 0; i < mRemoteVideoCells.size(); i++) {
            mRemoteVideoCells.get(i).setVisibility(i == 0 ? VISIBLE : GONE);
        }
    }



    @Override
    protected void onOrientationChanged(boolean isLandscape) {

    }


    @Override
    public synchronized void setRemoteVideoInfos(List<VideoInfo> infos) {
        if (infos != null && infos.size() > 0) {
            mRemoteVideoInfos = infos;

            //L.i(TAG, "video info: " + infos.get(0).getVideoWidth() + " " + infos.get(0).getVideoHeight());

            L.i(TAG, "setRemoteVideoInfos, mRemoteVideoInfos.size : " + mRemoteVideoInfos.size() + ", mRemoteVideoCells.size : " + mRemoteVideoCells.size());

            if (mRemoteVideoCells.size() > 0) {
                //1.compute none existed video cell
                List<VideoCell> toDel = new ArrayList<>();

                for (VideoCell cell : mRemoteVideoCells) {
                    for (int i = 0; i < mRemoteVideoInfos.size(); i++) {
                        VideoInfo info = mRemoteVideoInfos.get(i);
                        if (cell.getLayoutInfo() != null && cell.getLayoutInfo().getParticipantId() == info.getParticipantId()) {
                            break;
                        }

                        if (cell.getLayoutInfo() != null && cell.getLayoutInfo().getLayoutVideoState().equals(Enums.LAYOUT_STATE_ADDOTHER)) {
                            break;
                        }

                        if (i == mRemoteVideoInfos.size() - 1) {
                            toDel.add(cell);
                        }
                    }
                }

                L.i(TAG, "setRemoteVideoInfos, toDel.size : " + toDel.size());

                //2.delete none existed video cell
                for (VideoCell cell : toDel) {
                    if (cell.getId() != VideoCell.LOCAL_VIEW_ID) {
                        removeView(cell);
                        mRemoteVideoCells.remove(cell);
                    }
                }

                toDel.clear();
            }


            //3.update already exist cell & add new cell
            if (mRemoteVideoCells.size() > 0) {
                for (VideoInfo info : mRemoteVideoInfos) {
                    for (int i = 0; i < mRemoteVideoCells.size(); i++) {
                        VideoCell cell = mRemoteVideoCells.get(i);

                        //update already exit cell
                        if (cell.getLayoutInfo() != null && info.getParticipantId() == cell.getLayoutInfo().getParticipantId()) {
                            android.util.Log.d(TAG, "oldInfo : " + cell.getLayoutInfo());
                            android.util.Log.d(TAG, "newInfo : " + info);
                            if (info.getLayoutVideoState().equals(Enums.LAYOUT_STATE_MUTE)
                                    || info.getLayoutVideoState().equals(Enums.LAYOUT_STATE_REQUESTING)
                                    || info.getLayoutVideoState().equals(Enums.LAYOUT_STATE_AUDIO_ONLY)) {
                                info.setVideoHeight(cell.getLayoutInfo().getVideoHeight());
                                info.setVideoWidth(cell.getLayoutInfo().getVideoWidth());
                            }
                            cell.setLayoutInfo(info);
                            break;
                        }

                        //add new cell
                        if (i == mRemoteVideoCells.size() - 1) {
                            mRemoteVideoCells.add(createRemoteCell(info, false));
                        }
                    }
                }

                //reorder video cell
                for (int i = 0; i < mRemoteVideoInfos.size(); i++) {
                    for (int j = 0; j < mRemoteVideoCells.size(); j++) {
                        VideoCell cell = mRemoteVideoCells.get(j);
                        if (cell.getLayoutInfo() != null && mRemoteVideoInfos.get(i).getParticipantId() == cell.getLayoutInfo().getParticipantId()) {
                            if (i < j) {
                                mRemoteVideoCells.remove(cell);
                                mRemoteVideoCells.add(i, cell);
                                break;
                            }
                        }
                    }
                }
            } else {
                for (VideoInfo info : mRemoteVideoInfos) {
                    mRemoteVideoCells.add(createRemoteCell(info, false));
                }
            }

            L.i(TAG, "setRemoteVideoInfos,  mRemoteVideoCells.size : " + mRemoteVideoCells.size());

            //4.relayout accordingly child count & others
            post(mLayoutRunnabler);
        } else {
            //1. clean ui element
            for (VideoCell cell : mRemoteVideoCells) {
                if (cell.getId() != VideoCell.LOCAL_VIEW_ID) {
                    removeView(cell);
                    mRemoteVideoCells.remove(cell);
                }
            }

            //2. relayout accordingly child count & others
            post(mLayoutRunnabler);
            //3. clean up data
            if (mRemoteVideoInfos != null) {
                mRemoteVideoInfos.clear();
            }
        }
    }


    /**
     * 计算视频单元顺序
     */
    private synchronized void computeVideoCellOrders() {

        L.i(TAG, "computeVideoCellOrders");


        //添加local到窗口列表
        if (!mRemoteVideoCells.contains(mLocalVideoCell)) {
            addView(mLocalVideoCell);
            mRemoteVideoCells.add(mLocalVideoCell);
        }


        //设置local在底部第一位置
        if (mRemoteVideoCells.size() >= 2) {
            for (VideoCell cell : mRemoteVideoCells) {
                if (cell.getId() == VideoCell.LOCAL_VIEW_ID && cell.getLayoutInfo() != null
                        && cell.getLayoutInfo().getParticipantId() != 0) {
                    mRemoteVideoCells.remove(cell);
                    mRemoteVideoCells.add(1, cell);
                    break;
                }
            }
        }


        //邀请用户的cell排到最后
        List<VideoCell> addOhters = new ArrayList<>();
        for (VideoCell cell : mRemoteVideoCells) {
            if (cell.getLayoutInfo() != null && (cell.getLayoutInfo().getLayoutVideoState().equals(Enums.LAYOUT_STATE_ADDOTHER)
                    || cell.getLayoutInfo().getLayoutVideoState() == Enums.LAYOUT_STATE_ADDOTHER_FAILED)) {
                mRemoteVideoCells.remove(cell);
                addOhters.add(cell);
            }
        }

        mRemoteVideoCells.addAll(addOhters);

        //UI just support max six channel video, such as one local and five remote
        if (mRemoteVideoCells.size() > THUMBNAIL_CELL_NUM + 1) {
            List<VideoCell> toDel = mRemoteVideoCells.subList(THUMBNAIL_CELL_NUM + 1, mRemoteVideoCells.size());

            for (VideoCell cell : toDel) {
                removeView(cell);
                mRemoteVideoCells.remove(cell);
            }
        }

        L.i(TAG, "computeVideoCellOrders, mRemoteVideoCells.size : " + mRemoteVideoCells.size());
    }


    private VideoCell createRemoteCell(VideoInfo layoutInfo, boolean playCreateAnimation) {
        L.i(TAG, "createRemoteCell, remoteVidoeInfo : " + layoutInfo);
        VideoCell cell = new VideoCell(playCreateAnimation, getContext(), this);
        cell.setLayoutInfo(layoutInfo);
        cell.bringToFront();

        addView(cell);
        return cell;
    }

    @Override
    protected void createLocalCell(boolean isUvc) {
        L.i(TAG, "createLocalCell, isUvc : " + isUvc);
        mLocalVideoCell = new VideoCell(isUvc, false, getContext(), this);
        mLocalVideoCell.setId(VideoCell.LOCAL_VIEW_ID);
        mLocalVideoCell.bringToFront();
        mLocalVideoCell.setLayoutInfo(mLocalVideoInfo);
    }

    public void setLocalVideoState(boolean visible) {
        if (visible) {
            mLocalVideoCell.setVisibility(VISIBLE);
        } else {
            mLocalVideoCell.setVisibility(GONE);
        }
    }

}